package be.rhok.eenzaamheidswijzer.dao;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Transactional
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
    private final Class<T> type;

    protected static final String UNCHECKED = "unchecked";

    private HibernateTemplate hibernateTemplate;

    @Resource
    public final void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public final HibernateTemplate getHibernateTemplate() {
        hibernateTemplate.flush();
        return hibernateTemplate;
    }

    public BaseDaoImpl(Class<T> type) {
        this.type = type;
    }

    public Class<T> getType() {
        return type;
    }

    /**
     * {@inheritDoc}
     */
    public final T get(Object id) {
        return hibernateTemplate.get(type, (Serializable) id);
    }

    public T load(Object id) {
        return hibernateTemplate.load(type, (Serializable) id);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings(UNCHECKED)
    public final List<T> findAll() {
        return hibernateTemplate.find("from " + type.getSimpleName());
    }

    /**
     * {@inheritDoc}
     */
    public final T merge(T t) {
        return hibernateTemplate.merge(t);
    }

    /**
     * {@inheritDoc}
     */
    public final void persist(T t) {
        hibernateTemplate.persist(t);
    }

    /**
     * {@inheritDoc}
     */
    public final void update(T t) {
        hibernateTemplate.update(t);
    }

    /**
     * {@inheritDoc}
     */
    public final void saveOrUpdateAll(Collection<T> items) {
        hibernateTemplate.saveOrUpdateAll(items);
    }

    /**
     * {@inheritDoc}
     */
    public final void remove(T t) {
        hibernateTemplate.delete(t);
    }

    public final void remove(Collection<T> t) {
        hibernateTemplate.deleteAll(t);
    }

    public final void flush() {
        hibernateTemplate.flush();
    }

    /**
     * List.
     *
     * @param hql        the query string
     * @param parameters the query parameters
     * @return the result list
     */
    @SuppressWarnings(UNCHECKED)
    protected final List<T> list(String hql, Object... parameters) {
        return getHibernateTemplate().find(hql, parameters);
    }

    /**
     * List.
     *
     * @param hql the query string
     * @return the result list
     */
    @SuppressWarnings(UNCHECKED)
    protected final List<T> list(String hql) {
        return getHibernateTemplate().find(hql);
    }

    protected final Set<T> set(List<T> values) {
        Set<T> result = new HashSet<T>();
        result.addAll(values);
        return result;
    }

    protected final Query createQuery(String query) {
        return getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(query);
    }

}
